<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">
pre {margin-left:20pt; }
pre > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
pre > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table.header { border: 0px; border-spacing: 0;
  margin-left: 0px; font-style: normal; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none; 
  padding-right: 0.4em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none;
  padding-right: 0.4em; border: none; }
</style>

<title>A proposal to add a generalized callable negator (Revision 4)</title>
</head>

<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>N4076</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2014-06-17</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;</th><th> </th><td>Programming Language C++, Library Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td><address>Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</address></td>
  </tr>
</tbody></table>

<h1><a name="title">A proposal to add a generalized callable negator (Revision 4)</a></h1>

<h2><a name="intro">Introduction</a></h2>

<p>This proposal is to add function template <code>not_fn</code> that will allow to create negator of any callable object.</p>

<!--h2><a name="toc">Table of contents</a></h2-->

<h2><a name="revision">Revision history</a></h2>

<p>Changes since <a href="http://isocpp.org/files/papers/n4022.html">N4022</a>:</p>
<ul>
  <li>Changed the paragraph numbers to match newest working draft.</li>
  <li>Changed the requires clause to apply to constructed functor instead of function argument.</li>
  <li>Updated wording for <code>argument_type</code>, <code>first_argument_type</code> and <code>second_argument_type</code> 
      to match resolution of <a href="http://cplusplus.github.io/LWG/lwg-active.html#2387">LWG issue #2387</a>.</li>
  <li>Changed definition of <code>fn</code> to forwarding call wrapper.</li>
  <li>Replaced <code>decay&lt;F&gt;::type</code> with <code>decay_t&lt;F&gt;</code>.</li>
  <li>Corrected spelling mistakes in <a href="#motivation">Motivation and Scope</a> section.</li>
  <li>Removed nested typedefs and added note, based on LWG review.</li>
</ul>

<p>Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3800.html">N3800</a>:</p>
<ul>
  <li>Updated proposed wording per LWG guidance.</li>
</ul>

<p>Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3699.html">N3699</a>:</p>
<ul>
  <li>Changed the requirements of <code>not_fn</code> to allow wrapping of move-only types.</li>
  <li>Added missing Throws clause.</li>
  <li>Included changes to 20.9 [function.objects]/2 section.</li>
  <li>Corrected link to "Generic (Polymorphic) Lambda Expressions" proposal.</li>
  <li>Changed formating of the document.</li>
</ul>

<h2><a name="motivation">Motivation and Scope</a></h2>

<p>The standard negators <code>not1</code> and <code>not2</code> accept only unary and binary functors
   that define <code>argument_type</code> or <code>first_argument_type</code> and <code>second_argument_type</code> respectively,
   which make them unusable with results of standard library functions such as <code>bind</code> and <code>mem_fn</code>.
   Furthermore, with relation to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm">N3421</a>,
   they cannot be used with new operator functor specializations.</p>

<p>This proposal addresses the problem by introducing a template function <code>not_fn</code> that returns complement of arbitrary predicate.</p>

<h3><a name="motivation.lambda">Comparison with lambda</a></h3>

<p>While the polymorphic lambda expressions (<a href="http://isocpp.org/files/papers/N3649.html">N3649</a>) may be used to negate arbitrary functor,
   the proposed function offers more compact syntax:</p>
<pre>  std::partition(v.begin(), v.end(), [f](auto&amp; p) { return !f(p); });
  std::partition(v.begin(), v.end(), std::not_fn(f));
</pre>

<p>Furthermore, the use of lambda expression requires separate treatment of member pointers:</p>
<pre>  std::partition(v.begin(), v.end(), [pm](auto&amp; p) { return !std::mem_fn(pm)(p); });
  std::partition(v.begin(), v.end(), std::not_fn(pm));
</pre>

<h3><a name="motivation.depraction">Deprecation</a></h3>
<p>With the incorporation of proposed functionality the old standard negators should be deprecated.</p>

<h2><a name="design">Design Decisions</a></h2>

<h3><a name="design.specializations">New specializations of <code>unary_negate</code>, <code>binary_negate</code></a></h3>

<p>Problem addressed by this paper may be solved by introducing perfect forwarding specializations of <code>unary_negate</code> and
   <code>binary_negate</code> for types that do not define <code>argument_type</code> and <code>first_argument_type</code>,
   <code>second_argument_type</code> nested types respectively, without 
breaking existing code.
   Although this solution does not address functions with arbitrary 
number of arguments and requires additional implementation burden.</p>

<h3><a name="design.return">Return type</a></h3>

<p>The perfect forwarding of return type was chosen instead of hard-coded <code>bool</code>.
   Similar argumentation to the one provided in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm">N3421</a> applies.</p>

<p>In Rapperswil decided not to define this type.</p>

<h3><a name="design.argument">Argument typedefs</a></h3>

<p>The <code>argument_type</code>, <code>first_argument_type</code> and <code>second_argument_type</code>
   nested types are required by implementation to be consistent with most of library functors,
   that define these types where they are well defined for target callable type.
   Furthermore it is increasing the amount of existing code that will remain valid after changing <code>not1</code>,
   <code>not2</code> to <code>not_fn</code>.</p>

<p>In Rapperswil decided not to define these types.</p>

<h2><a name="standard">Impact On The Standard</a></h2>

<p>This proposal has no dependencies beyond a C++11 compiler and Standard Library implementation.
   (It depends on perfect forwarding, <code>decltype</code> and trailing return types.)</p>

<p>Nothing depends on this proposal.</p>

<h2><a name="wording">Proposed wording</a></h2>

<p>After the declaration of <code>not2</code> in the section 20.9 [function.objects]/2 (Header <code>&lt;functional&gt;</code> synopsis), add:</p>

<blockquote class="stdins"> 

<pre>  // 20.9.9, <em>negators</em>
  template &lt;class F&gt; <em>unspecified</em> not_fn(F&amp;&amp; f);
</pre>

</blockquote>


<p>After paragraph 20.9.8 Negators [negators], insert a new paragraph. (Chapter [bind] (Function template <code>bind</code>) becomes 20.9.?)</p>
  
<blockquote class="stdins"> 
<h4><a name="optional.general">20.9.9 Function template <code>not_fn</code> <span style="float:right">[not_fn]</span></a></h4>

<pre>  template &lt;class F&gt;
    <em>unspecified</em> not_fn(F&amp;&amp; f);
</pre>

  <dl class="attribute">

    <dd><p>In the text that follows:
    </p><ul>
      <li><code>FD</code> is the type <code>decay_t&lt;F&gt;</code>,</li>
      <li><code>fd</code> is an lvalue of type <code>FD</code> constructed from <code>std::forward&lt;F&gt;(f),</code>
      </li><li><code>fn</code> is a forwarding call wrapper created as a result of <code>not_fn(f)</code>,</li>
    </ul><p></p></dd>

    <dt>Requires:</dt> 
    <dd><code>is_constructible&lt;FD, F&gt;::value</code> shall be <code>true</code>.
        <code>fd</code> shall be a callable object ([func.def] 20.9.1).<p></p></dd>

    <dt>Returns:</dt>
    <dd><p>A forwarding call wrapper <code>fn</code> such that the expression <code>fn(a1, a2, ..., aN)</code> 
           is equivalent to <code>!<em>INVOKE</em>(fd, a1, a2, ..., aN)</code> ([func.require] 20.9.2).</p></dd>

    <dt>Throws:</dt>
    <dd><p>Nothing unless the construction of <code>fd</code> throws an exception.</p></dd>

    <dt>Remarks:</dt>
    <dd><p>The return type shall satisfy the requirements of <code>MoveConstructible</code>.
        If <code>FD</code> satisfies the requirements of <code>CopyConstructible</code>, then 
        the return type shall satisfy the requirements of <code>CopyConstructible</code>.
        [ <em>Note:</em> This implies that <code>FD</code> is MoveConstructible.
          <em> — end note</em> ]</p></dd>


     <dt></dt>
     <dd><p>[ <em>Note:</em> Function template <code>not_fn</code> can usually provide a better solution
    than using the negators <code>not1</code> and <code>not2</code>.
          <em> — end note</em> ]</p></dd>

  </dl>
</blockquote>

<h2><a name="acknowledgements">Acknowledgements</a></h2>

<p>Anna Salwa originally proposed <code>not_fn</code> in discussion group <a href="https://groups.google.com/a/isocpp.org/forum/?fromgroups#%21topic/std-proposals/ki4-jb5WzhA">ISO C++ Standard - Future Proposals</a>.</p>
<p>Mateusz Kwiatkowski, Jonathan Wakely and Daniel Krügler offered many useful suggestions and corrections to the proposal.</p>

<h2><a name="literature">References</a></h2>

<ol>
  <li>Stephan T. Lavavej, "Making Operator Functors greater&lt;&gt;" (N3421, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm</a>)</li>
  <li>Faisal Vali, Herb Sutter, Dave Abrahams, "Generic (Polymorphic) Lambda Expressions (Revision 3) " (N3649, <a href="http://isocpp.org/files/papers/N3649.html">http://isocpp.org/files/papers/N3649.html</a>)</li>
</ol>


</body></html>